//
//  ThemeStore.swift
//  DemoDarkMode
//
//  Created by zhuxuhong on 2022/3/30.
//

import UIKit

public protocol BWThemeColorStoreable {
    associatedtype StoreEnum
    
    static var filePath: URL? {get}
    static var shared: Self {get}
    
    var colorStore: BWThemeColorStore? {set get}
}


public extension BWThemeColorStoreable {
    static func loadStore() -> BWThemeColorStore? {
        guard
            let aURL = filePath,
            let data = try? Data(contentsOf: aURL) else {
                return nil
            }
        do {
            let store = try JSONDecoder().decode(BWThemeColorStore.self, from: data)
            return store
        } catch {
            print(error)
        }
        return nil
    }
    
    func findColor<Style: BWThemeStyle>(
        forStyle style: Style,
        atScope scopeName: String,
        colorName: String
    ) -> UIColor? {
        let foundStyle = colorStore?.styles.first{
            $0.name.lowercased() == "\(style)".lowercased()
        }
        let foundScope = foundStyle?.scopes.first{
            $0.name.lowercased() == scopeName
        }
        let foundColor = foundScope?.colors.first{
            $0.name.lowercased() == colorName.lowercased()
        }
        return foundColor?.uiColor
    }
    
    func getColor<ScopeEnum, Style: BWThemeStyle, Color: BWThemeColor>(
        forStyle style: Style,
        atScope scope: ScopeEnum.Type,
        color: Color
    ) -> UIColor? {
        let foundStyle = colorStore?.styles.first{
            $0.name.lowercased() == "\(style)".lowercased()
        }
        let foundScope = foundStyle?.scopes.first{
            $0.name.lowercased() == "\(scope)"
                .components(separatedBy: ".")
                .last?
                .lowercased()
        }
        let foundColor = foundScope?.colors.first{
            $0.name.lowercased() == "\(color)".lowercased()
        }
        return foundColor?.uiColor
    }
}

public struct BWThemeColorStore: Decodable {
    var name: String
    var styles: [BWThemeColorStoreStyle]
}

public struct BWThemeColorStoreStyle: Decodable {
    var name: String
    var scopes: [BWThemeColorStoreScope]
}

public struct BWThemeColorStoreScope: Decodable {
    var name: String
    var colors: [BWThemeColorStoreColor]
}

public struct BWThemeColorStoreColor: Decodable {
    var name: String
    var rgba: String
}

public extension BWThemeColorStoreColor {
    var uiColor: UIColor? {
        let comps = rgba.components(separatedBy: ", ")
        guard
            comps.count == 4,
            let r = Double(comps.first!),
            let g = Double(comps[1]),
            let b = Double(comps[2]),
            let a = Double(comps.last!) else {
                return nil
            }
        return .init(red: r/255, green: g/255, blue: b/255, alpha: a)
    }
}
